
#include <assert.h>
#include <memory.h>
#include <malloc.h>
#include <string.h>
#include "cvector.h"
#include "csort.h"
#include "csearch.h"

static void* StlcVectorFindVarg( const SVector* a_pstVector, size_t a_szIndex, va_list a_pArgList );
static SIterator StlcVectorSearchVarg( const SVector* a_pstVector, PFSearch a_pfnSearch, PFCompare a_pfnCompare, size_t a_szIndex, va_list a_pArgList );

SVector StlcVectorCreate( size_t a_szTypeSize, const char* a_pcTypeName )
{
	SVector stVector;
	assert( a_szTypeSize > 0 && NULL != a_pcTypeName );
	memset( &stVector, 0, sizeof( stVector ) );
	stVector.eContainerType = ECRT_VECTOR;
	StlcUnifyTypes( &stVector.stStlcType, a_szTypeSize, a_pcTypeName, NULL );
	return stVector;
}

void StlcVectorInit( PSVector a_pstVector, PFCompare a_pfnCompare )
{
	StlcVectorInitN( a_pstVector, a_pfnCompare, 0 );
}

void StlcVectorInitN( PSVector a_pstVector, PFCompare a_pfnCompare, size_t a_szCount )
{
	assert( NULL != a_pstVector );
	StlcVectorInitElem( a_pstVector, a_pfnCompare, a_szCount, 0x00 );
}

void StlcVectorInitElem( PSVector a_pstVector, PFCompare a_pfnCompare, size_t a_szCount, ... )
{
	va_list pArgList;
	size_t  i = 0;	
	assert( NULL != a_pstVector && NULL == a_pstVector->pcStart && NULL == a_pstVector->pcFinish 
		&& NULL == a_pstVector->pcEndOfStorage && NULL != a_pstVector->stStlcType.pfnCopy );
	va_start( pArgList, a_szCount );
	if( a_szCount > 0 )
	{
		a_pstVector->pcStart = (char*)StlcAlloc( a_pstVector->stStlcType.szTypeSize * 2 * a_szCount );
		assert( NULL != a_pstVector->pcStart );
		a_pstVector->pcFinish = a_pstVector->pcStart + a_pstVector->stStlcType.szTypeSize * a_szCount;
		a_pstVector->pcEndOfStorage = a_pstVector->pcStart + a_pstVector->stStlcType.szTypeSize * 2 * a_szCount;	
		
		for( i = 0; i < a_szCount; ++i )
		{
			a_pstVector->stStlcType.pfnCopy( a_pstVector->pcStart + i * a_pstVector->stStlcType.szTypeSize, pArgList, a_pstVector->stStlcType.szTypeSize );
		}		
	}
	a_pstVector->stStlcType.pfnCompare = ( NULL != a_pfnCompare ) ? a_pfnCompare : a_pstVector->stStlcType.pfnCompare;
}

void StlcVectorInitCopy( PSVector a_pstVectorDest, const SVector* a_pstVectorSrc )
{
	StlcVectorInitCopyRange( a_pstVectorDest, StlcVectorBegin( a_pstVectorSrc ), StlcVectorEnd( a_pstVectorSrc ) );
}

void StlcVectorInitCopyRange( PSVector a_pstVectorDest, const SIterator a_stIterBegin, const SIterator a_stIterEnd )
{
	SIterator stIteratorSrc = {0}, stIteratorDest = {0};
	assert( NULL != a_pstVectorDest && NULL != a_stIterBegin.pstContainer && NULL != a_stIterEnd.pstContainer );
	assert(	StlcSameType( &a_pstVectorDest->stStlcType, &((PSVector)a_stIterBegin.pstContainer)->stStlcType ) );
	assert(	NULL == a_pstVectorDest->pcStart && NULL == a_pstVectorDest->pcFinish
		&& NULL == a_pstVectorDest->pcEndOfStorage && NULL == a_pstVectorDest->stStlcType.pfnCompare );
	assert( StlcVectorIteratorEqual( (PSVector)a_stIterBegin.pstContainer, a_stIterBegin, a_stIterEnd ) 
		|| StlcVectorIteratorBefore( a_stIterBegin, a_stIterEnd ));

	StlcVectorInitN( a_pstVectorDest, ((PSVector)a_stIterBegin.pstContainer)->stStlcType.pfnCompare,
		StlcVectorIteratorDistance( (PSVector)a_stIterBegin.pstContainer, a_stIterBegin, a_stIterEnd ) );
	memcpy( a_pstVectorDest->pcStart, a_stIterBegin.pcCurPos, a_stIterEnd.pcCurPos - a_stIterBegin.pcCurPos );
}

bool StlcVectorSameType( const SVector* a_pstVectorFirst, const SVector* a_pstVectorSecond )
{
	assert( NULL != a_pstVectorFirst && NULL != a_pstVectorFirst );
	return StlcSameType( &a_pstVectorFirst->stStlcType, &a_pstVectorSecond->stStlcType );
}

size_t StlcVectorSize( const SVector* a_pstVector )
{
	assert( NULL != a_pstVector );
	return (size_t)( a_pstVector->pcFinish - a_pstVector->pcStart ) / a_pstVector->stStlcType.szTypeSize;
}

bool StlcVectorEmpty( const SVector* a_pstVector )
{
	assert( NULL != a_pstVector );
	return ( a_pstVector->pcStart == a_pstVector->pcFinish ) ? true : false;
}

size_t StlcVectorMaxSize( const SVector* a_pstVector )
{
	assert( NULL != a_pstVector );
	return (size_t)(-1) / a_pstVector->stStlcType.szTypeSize;
}

size_t StlcVectorCapacity( const SVector* a_pstVector )
{
	assert( NULL != a_pstVector );
	return (size_t)( a_pstVector->pcEndOfStorage - a_pstVector->pcStart) / a_pstVector->stStlcType.szTypeSize;
}

void StlcVectorReserve( PSVector a_pstVector, size_t a_szReserveSize )
{
	char*  pNewMem = NULL; 
	assert( NULL != a_pstVector );
	if( StlcVectorCapacity( a_pstVector) < a_szReserveSize )
	{		
		size_t szOldSize = (size_t)( a_pstVector->pcFinish - a_pstVector->pcStart );
		pNewMem = StlcAlloc( a_pstVector->stStlcType.szTypeSize * a_szReserveSize );
		assert( NULL != pNewMem );						
		if( NULL != a_pstVector->pcStart )
		{
			memcpy( pNewMem, a_pstVector->pcStart, szOldSize );
			StlcFree( a_pstVector->pcStart );
		}
		a_pstVector->pcStart = pNewMem;
		a_pstVector->pcFinish = a_pstVector->pcStart + szOldSize;
		a_pstVector->pcEndOfStorage = a_pstVector->pcStart + ( a_pstVector->stStlcType.szTypeSize * a_szReserveSize );
	}
}

bool StlcVectorEqual( const SVector* a_pstVectorFirst, const SVector* a_pstVectorSecond )
{
	int   i = 0;
	void *pFirst = NULL, *pSecond = NULL;     /* the second vector core pointer */
	assert( NULL != a_pstVectorFirst && NULL != a_pstVectorSecond );
	/* the element type is equal */
	if( StlcSameType( &a_pstVectorFirst->stStlcType, &a_pstVectorSecond->stStlcType ) )
	{
		return false;
	}	
	
	/* the element count is equal */
	if( StlcVectorSize( a_pstVectorFirst ) != StlcVectorSize( a_pstVectorSecond ) )
	{
		return false;
	}

	/* if have the user equal function for each element */
	if( NULL != a_pstVectorFirst->stStlcType.pfnCompare )
	{
		/* each element is equal */
		for( i = StlcVectorSize( a_pstVectorFirst ) - 1; i >= 0; --i )
		{
			pFirst  = a_pstVectorFirst->pcStart  + a_pstVectorFirst->stStlcType.szTypeSize  * i;
			pSecond = a_pstVectorSecond->pcStart + a_pstVectorSecond->stStlcType.szTypeSize * i;

			if( (*a_pstVectorFirst->stStlcType.pfnCompare)( pFirst, pSecond ) != 0 )
			{
				return false;
			}
		}
	}
	else
	{
		/* compare the memory for test */
		if( 0 != memcmp( a_pstVectorFirst->pcStart, a_pstVectorSecond->pcStart,
			a_pstVectorFirst->pcFinish - a_pstVectorFirst->pcStart ) )
		{
			return false;
		}
	}
	return true;
}

bool StlcVectorNotEqual( const SVector* a_pstVectorFirst, const SVector* a_pstVectorSecond )
{
	return !StlcVectorEqual( a_pstVectorFirst, a_pstVectorSecond );
}

bool StlcVectorLess( const SVector* a_pstVectorFirst, const SVector* a_pstVectorSecond )
{
	return true;
}

bool StlcVectorGreat( const SVector* a_pstVectorFirst, const SVector* a_pstVectorSecond )
{
	return true;
}

bool StlcVectorLessEqual( const SVector* a_pstVectorFirst, const SVector* a_pstVectorSecond )
{
	return true;
}

bool StlcVectorGreatEqual( const SVector* a_pstVectorFirst, const SVector* a_pstVectorSecond )
{
	return true;
}

void StlcVectorAssign( PSVector a_pstVectorDest, const SVector* a_pstVectorSrc )
{
	assert( NULL != a_pstVectorDest && NULL != a_pstVectorSrc );
	assert( StlcSameType( &a_pstVectorDest->stStlcType, &a_pstVectorSrc->stStlcType ) );
	StlcVectorDestroy( a_pstVectorDest );
	StlcVectorInitCopy( a_pstVectorDest, a_pstVectorSrc );
}

void StlcVectorAssignRange( PSVector a_pstVector, const SIterator *a_pstIterBegin, const SIterator *a_pstIterEnd )
{	
	assert( NULL != a_pstVector && NULL != a_pstIterBegin && NULL != a_pstIterEnd 
		&& NULL != a_pstIterBegin->pstContainer && NULL != a_pstIterEnd->pstContainer 
		&& a_pstIterBegin->pstContainer == a_pstIterEnd->pstContainer 
		&& ECRT_VECTOR == a_pstIterBegin->eContainerType && ECRT_VECTOR == a_pstIterEnd->eContainerType
		&& EIRT_RANDOM_ACCESS == a_pstIterBegin->eIteratorType && EIRT_RANDOM_ACCESS == a_pstIterEnd->eIteratorType);
	assert( StlcSameType( &a_pstVector->stStlcType, &((PSVector)a_pstIterBegin->pstContainer)->stStlcType ) );
	assert( a_pstVector->stStlcType.pfnCompare == ((PSVector)a_pstIterBegin->pstContainer)->stStlcType.pfnCompare );
	assert( StlcVectorIteratorEqual( (PSVector)a_pstIterBegin->pstContainer, *a_pstIterBegin, *a_pstIterEnd )
		|| StlcVectorIteratorBefore( *a_pstIterBegin, *a_pstIterEnd ) );	
	StlcVectorDestroy( a_pstVector );
	StlcVectorInitCopyRange( a_pstVector, *a_pstIterBegin, *a_pstIterEnd );
}

void StlcVectorSwap( PSVector a_pstVectorFirst, PSVector a_pstVectorSecond )
{
	SVector stVector = {0};
	assert( NULL != a_pstVectorFirst && NULL != a_pstVectorSecond );
	assert( StlcSameType( &a_pstVectorFirst->stStlcType, &a_pstVectorSecond->stStlcType ) );
	stVector = *a_pstVectorFirst;
	*a_pstVectorFirst = *a_pstVectorSecond;
	*a_pstVectorSecond = stVector;
}

void* StlcVectorAt( const SVector* a_pstVector, size_t a_szPos )
{
	assert( NULL != a_pstVector && NULL != a_pstVector->pcStart && a_szPos < StlcVectorSize( a_pstVector ) );
	return a_pstVector->pcStart + a_szPos * a_pstVector->stStlcType.szTypeSize;
}

void* StlcVectorFront( const SVector* a_pstVector )
{
	if( StlcVectorEmpty( a_pstVector ) )
	{
		return NULL;
	}
	else
	{
		return StlcVectorAt( a_pstVector, 0 );
	}
}

void* StlcVectorBack( const SVector* a_pstVector )
{
	if( StlcVectorEmpty( a_pstVector ) )
	{
		return NULL;
	}
	else
	{
		return StlcVectorAt( a_pstVector, StlcVectorSize( a_pstVector ) - 1 );
	}
}

SIterator StlcVectorBegin( const SVector* a_pstVector )
{
	SIterator stIterator = {0};
	assert( NULL != a_pstVector );

	stIterator = StlcVectorIteratorCreate();
	stIterator.pstContainer = (void*)a_pstVector;
	stIterator.pcCurPos = a_pstVector->pcStart;
	return stIterator;
}

SIterator StlcVectorEnd( const SVector* a_pstVector )
{
	SIterator stIterator = {0};
	assert( NULL != a_pstVector );

	stIterator = StlcVectorIteratorCreate();
	stIterator.pstContainer = (void*)a_pstVector;
	stIterator.pcCurPos = a_pstVector->pcFinish;
	return stIterator;
}

void StlcVectorInsertRange( PSVector a_pstVector, PSIterator a_pstIterator, PSIterator a_pstIterBegin, PSIterator a_pstIterEnd )
{
	size_t szCount = 0; /* the element count */

	assert( StlcVectorIteratorBelongTo( a_pstVector, *a_pstIterator ) );
	assert( StlcVectorIteratorEqual( a_pstVector, *a_pstIterBegin, *a_pstIterEnd )
		|| StlcVectorIteratorBefore( *a_pstIterBegin, *a_pstIterEnd ) );
	assert( StlcVectorSameType( a_pstVector, a_pstIterBegin->pstContainer ) );

	szCount = StlcVectorIteratorDistance( a_pstVector, *a_pstIterBegin, *a_pstIterEnd );	
	if( StlcVectorSize( a_pstVector ) + szCount > StlcVectorCapacity( a_pstVector ) )
	{
		size_t szDistance = (size_t)( a_pstIterator->pcCurPos - a_pstVector->pcStart );		
		StlcVectorReserve(	a_pstVector, StlcVectorSize( a_pstVector ) + 2 * szCount );
		a_pstIterator->pcCurPos = a_pstVector->pcStart + szDistance;
	}	
	memmove( a_pstIterator->pcCurPos + szCount * a_pstVector->stStlcType.szTypeSize,
		a_pstIterator->pcCurPos, a_pstVector->pcFinish - a_pstIterator->pcCurPos ); 
	a_pstVector->pcFinish += szCount * a_pstVector->stStlcType.szTypeSize,
	memcpy(	a_pstIterator->pcCurPos, a_pstIterBegin->pcCurPos, szCount * a_pstVector->stStlcType.szTypeSize );
	a_pstVector->bSorted = false;
	a_pstVector->pfnSortComp = NULL;
}

void StlcVectorPushBack( PSVector a_pstVector, ... )
{
	va_list pArgList;	
	assert( NULL != a_pstVector );
	va_start( pArgList, a_pstVector );

	if( StlcVectorCapacity( a_pstVector ) == StlcVectorSize( a_pstVector ) ) 
	{
		size_t szReserveSize =  StlcVectorSize( a_pstVector );
		StlcVectorReserve( a_pstVector, ( 0 == szReserveSize ) ? 1 : 2 * szReserveSize );
	}
	a_pstVector->stStlcType.pfnCopy( a_pstVector->pcFinish, pArgList, a_pstVector->stStlcType.szTypeSize );
	a_pstVector->pcFinish += a_pstVector->stStlcType.szTypeSize;
	a_pstVector->bSorted = false;
	a_pstVector->pfnSortComp = NULL;	
}

void StlcVectorPopBack(  PSVector a_pstVector )
{
	assert( NULL != a_pstVector && StlcVectorSize( a_pstVector ) > 0 );
	a_pstVector->pcFinish -= a_pstVector->stStlcType.szTypeSize;
}

size_t StlcVectorErase( PSVector a_pstVector, ... )
{
	va_list pArgList;
	int nCount = 0, i = 0;;
	assert( NULL != a_pstVector && NULL != a_pstVector->stStlcType.pfnCompare );
	va_start( pArgList, a_pstVector );
	for( i = (int)StlcVectorSize( a_pstVector ) - 1; i >= 0; --i )
	{
		if( 0 == a_pstVector->stStlcType.pfnCompare( pArgList, 
			a_pstVector->pcStart + i * a_pstVector->stStlcType.szTypeSize ) )
		{
			memcpy( a_pstVector->pcStart + i * a_pstVector->stStlcType.szTypeSize, a_pstVector->pcStart + ( i + 1 ) * a_pstVector->stStlcType.szTypeSize,
				a_pstVector->pcFinish - a_pstVector->pcStart - ( i + 1 ) * a_pstVector->stStlcType.szTypeSize );
			a_pstVector->pcFinish -= a_pstVector->stStlcType.szTypeSize;
			++nCount;
		}
	}
	return (size_t)nCount;
}

SIterator StlcVectorErasePos( PSVector a_pstVector, SIterator a_stIterator )
{
	assert( NULL != a_pstVector && a_pstVector == a_stIterator.pstContainer );
	assert( StlcVectorIteratorBelongTo( a_pstVector, a_stIterator ) 
		&& !StlcVectorIteratorEqual( a_pstVector, a_stIterator, StlcVectorEnd( a_pstVector ) ) );
	memmove( a_stIterator.pcCurPos, a_stIterator.pcCurPos + a_pstVector->stStlcType.szTypeSize,
		a_pstVector->pcFinish - a_stIterator.pcCurPos - a_pstVector->stStlcType.szTypeSize );
	a_pstVector->pcFinish -= a_pstVector->stStlcType.szTypeSize;
	return a_stIterator;
}

SIterator StlcVectorEraseRange( PSVector a_pstVector, SIterator a_stIterBegin, SIterator a_stIterEnd )
{
	size_t szEraseSize = 0;

	assert( StlcVectorIteratorBelongTo( a_pstVector, a_stIterBegin ) );
	assert( StlcVectorIteratorEqual( a_pstVector, a_stIterBegin, a_stIterEnd )
		|| StlcVectorIteratorBefore( a_stIterBegin, a_stIterEnd ) );
	assert( !StlcVectorIteratorEqual( a_pstVector, a_stIterBegin, StlcVectorEnd( a_pstVector ) ) );

	szEraseSize = StlcVectorIteratorDistance( a_pstVector, a_stIterBegin, a_stIterEnd );
	memmove( a_stIterBegin.pcCurPos, a_stIterEnd.pcCurPos, a_pstVector->pcFinish - a_stIterEnd.pcCurPos );
	a_pstVector->pcFinish -= szEraseSize * a_pstVector->stStlcType.szTypeSize;
	return a_stIterBegin;
}

void StlcVectorResize( PSVector a_pstVector, size_t a_szResize )
{
	//vector_resize_elem(pt_vector, t_resize, 0x00);
}

void StlcVectorClear( PSVector a_pstVector )
{
	StlcVectorEraseRange( a_pstVector, StlcVectorBegin( a_pstVector ), StlcVectorEnd( a_pstVector ) );
}

void StlcVectorSort( PSVector a_pstVector, PFSort a_pfnSort, PFCompare a_pfnCompare )
{
	assert( NULL != a_pstVector && NULL != a_pfnSort && NULL != a_pfnCompare );
	a_pfnSort( a_pstVector->pcStart, StlcVectorSize( a_pstVector ),	a_pstVector->stStlcType.szTypeSize, a_pfnCompare );
	a_pstVector->bSorted = true;
	a_pstVector->pfnSortComp = a_pfnCompare;
}

void* StlcVectorFind( const SVector* a_pstVector, ... )
{
	va_list    pArgList;
	va_start( pArgList, a_pstVector );
	return StlcVectorFindVarg( a_pstVector, 0, pArgList );		
}

void* StlcVectorFindN( const SVector* a_pstVector, size_t a_szIndex, ... )
{
	va_list    pArgList;
	va_start( pArgList, a_szIndex );
	return StlcVectorFindVarg( a_pstVector, a_szIndex, pArgList );	
}

void* StlcVectorFindVarg( const SVector* a_pstVector, size_t a_szIndex, va_list a_pArgList )
{
	void      *pFindValue = NULL;	
	assert( NULL != a_pstVector && NULL != a_pstVector->stStlcType.pfnCompare );
	
	if( a_pstVector->bSorted && a_pstVector->pfnSortComp == a_pstVector->stStlcType.pfnCompare )
	{
		SIterator stIterator = StlcVectorSearchVarg( a_pstVector, StlcBinarySearch, a_pstVector->stStlcType.pfnCompare, a_szIndex, a_pArgList );
		pFindValue = StlcVectorIteratorEqual( a_pstVector, stIterator, StlcVectorEnd( a_pstVector ) ) ? NULL : stIterator.pcCurPos;
	}
	else
	{
		size_t i = 0, szCount = 0, szSize = StlcVectorSize( a_pstVector );
		assert( NULL != a_pstVector->stStlcType.pfnCompare );
		for( i = 0; i < szSize; ++i )
		{
			if( 0 == a_pstVector->stStlcType.pfnCompare( a_pArgList, 
				a_pstVector->pcStart + i * a_pstVector->stStlcType.szTypeSize ) )
			{
				if( szCount++ == a_szIndex )
				{
					pFindValue = a_pstVector->pcStart + i * a_pstVector->stStlcType.szTypeSize;
				}				
			} 
		}		
	}		
	return pFindValue;
}

SIterator StlcVectorSearch( const SVector* a_pstVector, PFSearch a_pfnSearch, PFCompare a_pfnCompare, ... )
{	
	va_list pArgList;
	va_start( pArgList, a_pfnCompare );
	return StlcVectorSearchVarg( a_pstVector, a_pfnSearch, a_pfnCompare, 0, pArgList );
}

SIterator StlcVectorSearchN( const SVector* a_pstVector, PFSearch a_pfnSearch, PFCompare a_pfnCompare, size_t a_szIndex, ... )
{
	va_list pArgList;
	va_start( pArgList, a_pfnCompare );
	return StlcVectorSearchVarg( a_pstVector, a_pfnSearch, a_pfnCompare, a_szIndex, pArgList );
}

SIterator StlcVectorSearchVarg( const SVector* a_pstVector, PFSearch a_pfnSearch, PFCompare a_pfnCompare, size_t a_szIndex, va_list a_pArgList )
{	
	SIterator  stIterator = StlcVectorIteratorCreate();
	assert( NULL != a_pstVector && NULL != a_pfnSearch && NULL != a_pfnCompare && NULL != a_pArgList );
	assert( a_pstVector->bSorted && a_pstVector->pfnSortComp == a_pstVector->stStlcType.pfnCompare );	
	stIterator.pstContainer = (void*)a_pstVector;
	stIterator.pcCurPos = a_pfnSearch( a_pArgList, a_pstVector->pcStart,  StlcVectorSize( a_pstVector ), a_pstVector->stStlcType.szTypeSize, a_pfnCompare );	
	return ( NULL == stIterator.pcCurPos ) ? StlcVectorEnd( a_pstVector ) : stIterator;
}

void StlcVectorDestroy( PSVector a_pstVector )
{
	assert( NULL != a_pstVector && a_pstVector->pcFinish - a_pstVector->pcStart >= 0
		&& a_pstVector->pcEndOfStorage - a_pstVector->pcFinish >= 0 );
	if( NULL != a_pstVector->pcStart )
	{
		StlcFree( a_pstVector->pcStart );
	}
	memset( a_pstVector, 0, sizeof( SVector ) );
}

SIterator StlcVectorIteratorCreate(void)
{
	SIterator stIterator = {0};
	memset( &stIterator, 0, sizeof( stIterator ) );	
	stIterator.eContainerType = ECRT_VECTOR;
	stIterator.eIteratorType  = EIRT_RANDOM_ACCESS;
	return stIterator;
}

bool StlcVectorIteratorBelongTo( const SVector* a_pstVector, const SIterator a_stIterator )
{
	if( NULL != a_pstVector	&& a_pstVector == a_stIterator.pstContainer
		&& a_stIterator.pcCurPos >= a_pstVector->pcStart
		&& a_stIterator.pcCurPos <  ( a_pstVector->pcFinish + a_pstVector->stStlcType.szTypeSize )
		&& 0 == ( a_stIterator.pcCurPos - a_pstVector->pcStart ) % a_pstVector->stStlcType.szTypeSize )
	{
		return true;
	}
	return false;	
}

bool StlcVectorIteratorEqual( const SVector* a_pstVector, const SIterator a_stIterFirst, const SIterator a_stIterSecond )
{
	assert(	StlcVectorIteratorBelongTo( a_pstVector, a_stIterFirst )
		&& StlcVectorIteratorBelongTo( a_pstVector, a_stIterSecond ) );
	if( 0 == memcmp( &a_stIterFirst, &a_stIterSecond, sizeof( SIterator ) ) )
	{
		return true;
	}
	return false;
}

void StlcVectorIteratorGetValue( const SVector* a_pstVector,const SIterator a_stIterator, void* a_pValue )
{
	assert( StlcVectorIteratorBelongTo( a_pstVector, a_stIterator ) && NULL != a_pValue );	
	assert( StlcVectorSize( a_pstVector ) > 0 );
	assert( !StlcVectorIteratorEqual( a_pstVector, a_stIterator, StlcVectorEnd( a_pstVector ) ) );
	memcpy(	a_pValue, a_stIterator.pcCurPos, a_pstVector->stStlcType.szTypeSize );
}

void StlcVectorIteratorSetValue( const SVector* a_pstVector, const SIterator a_stIterator, void* a_pValue )
{
	assert( StlcVectorIteratorBelongTo( a_pstVector, a_stIterator ) && NULL != a_pValue );	
	assert( StlcVectorSize( a_pstVector ) > 0 );
	assert( !StlcVectorIteratorEqual( a_pstVector, a_stIterator, StlcVectorEnd( a_pstVector ) ) );
	memcpy( a_stIterator.pcCurPos, a_pValue, a_pstVector->stStlcType.szTypeSize );
}

const void* StlcVectorIteratorGetPointer( const SVector* a_pstVector, const SIterator a_stIterator )
{
	assert( StlcVectorIteratorBelongTo( a_pstVector, a_stIterator ) );
	assert( !StlcVectorIteratorEqual( a_pstVector, a_stIterator, StlcVectorEnd( a_pstVector ) ) );
	return a_stIterator.pcCurPos;
}

void StlcVectorIteratorNext( const SVector* a_pstVector, PSIterator a_pstIterator )
{
	assert( StlcVectorIteratorBelongTo( a_pstVector, *a_pstIterator ) );
	a_pstIterator->pcCurPos += a_pstVector->stStlcType.szTypeSize;
	assert( StlcVectorIteratorBelongTo( a_pstVector, *a_pstIterator ) );
}

void StlcVectorIteratorPrev( const SVector* a_pstVector, PSIterator a_pstIterator )
{
	assert( StlcVectorIteratorBelongTo( a_pstVector, *a_pstIterator ) );
	a_pstIterator->pcCurPos -= a_pstVector->stStlcType.szTypeSize;
	assert( StlcVectorIteratorBelongTo( a_pstVector, *a_pstIterator ) );
}

void* StlcVectorIteratorAt( const SVector* a_pstVector, const SIterator a_stIterator, size_t a_szIndex )
{
	char* pc_indexpos = NULL;
	assert( StlcVectorIteratorBelongTo( a_pstVector, a_stIterator ) );
	assert( a_stIterator.pcCurPos + a_pstVector->stStlcType.szTypeSize * a_szIndex < a_pstVector->pcFinish );
	return a_stIterator.pcCurPos + a_pstVector->stStlcType.szTypeSize * a_szIndex;
}

void StlcVectorIteratorNextN( const SVector* a_pstVector, PSIterator a_pstIterator, int a_nStep )
{
	assert( StlcVectorIteratorBelongTo( a_pstVector, *a_pstIterator ) );
	a_pstIterator->pcCurPos += a_pstVector->stStlcType.szTypeSize * a_nStep;
	assert( StlcVectorIteratorBelongTo( a_pstVector, *a_pstIterator ) );
}

void StlcVectorIteratorPrevN( const SVector* a_pstVector, PSIterator a_pstIterator, int a_nStep )
{
	assert( StlcVectorIteratorBelongTo( a_pstVector, *a_pstIterator ) );
	a_pstIterator->pcCurPos -= a_pstVector->stStlcType.szTypeSize * a_nStep;
	assert( StlcVectorIteratorBelongTo( a_pstVector, *a_pstIterator ) );
}

int StlcVectorIteratorDistance( const SVector* a_pstVector, const SIterator a_stIterFirst, const SIterator a_stIterSecond )
{
	assert( StlcVectorIteratorBelongTo( a_pstVector, a_stIterFirst ) 
		&& StlcVectorIteratorBelongTo( a_pstVector, a_stIterSecond ) );
	return (int)( a_stIterFirst.pcCurPos - a_stIterSecond.pcCurPos ) / (int)a_pstVector->stStlcType.szTypeSize;
}

bool StlcVectorIteratorLess( const SVector* a_pstVector, const SIterator a_stIterFirst, const SIterator a_stIterSecond )
{
	assert( StlcVectorIteratorBelongTo( a_pstVector, a_stIterFirst ) 
		&& StlcVectorIteratorBelongTo( a_pstVector, a_stIterSecond ) );
	assert( NULL != a_stIterFirst.pcCurPos && NULL != a_stIterSecond.pcCurPos );
	if( a_stIterFirst.pcCurPos < a_stIterSecond.pcCurPos )
	{
		return true;
	}
	else
	{
		return false;
	}
}

bool StlcVectorIteratorBefore( const SIterator a_stIterFirst, const SIterator a_stIterSecond )
{
	assert( NULL != a_stIterFirst.pstContainer && NULL != a_stIterFirst.pcCurPos 
		&& NULL != a_stIterSecond.pcCurPos && a_stIterFirst.pstContainer == a_stIterSecond.pstContainer );
	if( a_stIterFirst.pcCurPos < a_stIterSecond.pcCurPos )
	{
		return true;
	}
	else
	{
		return false;
	}
}